/*******************************************************************************
 * Copyright (C) 2010 Devin Samarin.
 * 
 * This file is part of the SUIT Toolkit.
 * 
 * The SUIT Toolkit is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * The SUIT Toolkit is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with the SUIT Toolkit.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
package suit.ui;

/**
 * A color object with a nifty little blend() function.
 * 
 * @author Devin Samarin
 * 
 */
public class Color {

	/**
	 * The red component of the color
	 */
	public int r;
	/**
	 * The green component of the color
	 */
	public int g;
	/**
	 * The blue component of the color
	 */
	public int b;
	/**
	 * The alpha component of the color
	 */
	public int a;

	/**
	 * Constructs a new color using an integer as the value. The value is in
	 * ARGB format (4-bytes).
	 * 
	 * @param color
	 *            the integer value for the color
	 */
	public Color(int color) {
		setInt(color);
	}

	/**
	 * Constructs a new color using the values of red, green, and blue
	 * separately. The alpha color is opaque by default (0xFF).
	 * 
	 * @param r
	 *            the red component (0-255)
	 * @param g
	 *            the green component (0-255)
	 * @param b
	 *            the blue component (0-255)
	 */
	public Color(int r, int g, int b) {
		this.r = r;
		this.g = g;
		this.b = b;
		this.a = 0xFF;
	}

	/**
	 * Constructs a new color using the values of red, green, blue, and alpha
	 * separately.
	 * 
	 * @param r
	 *            the red component (0-255)
	 * @param g
	 *            the green component (0-255)
	 * @param b
	 *            the blue component (0-255)
	 * @param a
	 *            the alpha component (0-255)
	 */
	public Color(int r, int g, int b, int a) {
		this.r = r;
		this.g = g;
		this.b = b;
		this.a = a;
	}

	/**
	 * Sets the color with an integer value
	 * 
	 * @param color
	 *            an integer value of the color in ARGB format
	 */
	public void setInt(int color) {
		a = ((color >> 24) & 0xff);
		r = ((color >> 16) & 0xff);
		g = ((color >> 8) & 0xff);
		b = ((color >> 0) & 0xff);
	}

	/**
	 * Gets the red component.
	 * 
	 * @return the red component (0-255)
	 */
	public int getRed() {
		return r;
	}

	/**
	 * Gets the green component.
	 * 
	 * @return the green component (0-255)
	 */
	public int getGreen() {
		return g;
	}

	/**
	 * Gets the blue component.
	 * 
	 * @return the blue component (0-255)
	 */
	public int getBlue() {
		return b;
	}

	/**
	 * Gets the alpha component.
	 * 
	 * @return the alpha component (0-255)
	 */
	public int getAlpha() {
		return a;
	}

	/**
	 * Gets the brightness of the color. This is done by calculating: (r + g +
	 * b) / 3. This does not take the alpha value into account.
	 * 
	 * @return the brightness of the color (0-255)
	 */
	public int getBrightness() {
		return (r + g + b) / 3;
	}

	/**
	 * Returns the integer value of the color in ARGB format
	 * 
	 * @return the integer value of the color in ARGB format
	 */
	public int value() {
		return (a << 24) | (r << 16) | (g << 8) | (b);
	}

	/**
	 * Takes the color and blends it with another color by a certain amount.
	 * 
	 * @param c
	 *            the color object to blend with
	 * @param p
	 *            the amount to blend; this is a value from 0 - 1 (0 is no
	 *            blending and all)
	 * @return a new color
	 */
	public Color blend(Color c, double p) {
		int x, y, z, a;
		a = (int) (this.a + (double) (p * (double) (c.a - this.a)));
		x = (int) (this.r + (double) (p * (double) (c.r - this.r)));
		y = (int) (this.g + (double) (p * (double) (c.g - this.g)));
		z = (int) (this.b + (double) (p * (double) (c.b - this.b)));
		return new Color(x, y, z, a);
	}
}
